package com.uprr.netcontrol.starmap.rest.converter;

import java.util.ArrayList;
import java.util.List;

import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.BusinessFunction;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.BusinessFunctionEventType;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.BusinessFunctionOther;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.BusinessFunctionServiceType;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.ContainerClusterServer;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.DeploymentUnit;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.Host;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.MessagingChannel;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.Monitor;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.Repository;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.Resource;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.ResourceEventType;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.ResourceServiceType;
import com.up.www.schemas.netcontrol.common.starmap.nc_du_deployment_descriptor_1_0.ServerClusterServer;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionDTO;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionEventTypeDTO;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionOtherDTO;
import com.uprr.netcontrol.starmap.dto.BusinessFunctionServiceTypeDTO;
import com.uprr.netcontrol.starmap.dto.ContainerClusterDTO;
import com.uprr.netcontrol.starmap.dto.ContainerClusterServerDTO;
import com.uprr.netcontrol.starmap.dto.DeploymentUnitDTO;
import com.uprr.netcontrol.starmap.dto.DistributionPackageDTO;
import com.uprr.netcontrol.starmap.dto.HostDTO;
import com.uprr.netcontrol.starmap.dto.MessageChannelInstanceDTO;
import com.uprr.netcontrol.starmap.dto.MessagingChannelDTO;
import com.uprr.netcontrol.starmap.dto.MonitorDTO;
import com.uprr.netcontrol.starmap.dto.RepositoryDTO;
import com.uprr.netcontrol.starmap.dto.ResourceDTO;
import com.uprr.netcontrol.starmap.dto.ResourceEventTypeDTO;
import com.uprr.netcontrol.starmap.dto.ResourceServiceTypeDTO;
import com.uprr.netcontrol.starmap.dto.ServerClusterDTO;
import com.uprr.netcontrol.starmap.dto.ServerClusterServerDTO;
import com.uprr.netcontrol.starmap.dto.ServerLogsDTO;

/*
 * This class is responsible for converting schematype to our Dto
 */
public class DeploymentUnitDtoConverter {

  public DeploymentUnitDtoConverter() {
    super();
  }

  public static DeploymentUnitDTO convert(final DeploymentUnit schemaType) throws Exception {
    DeploymentUnitDTO deploymentUnitDto = populateDeploymentUnitDTO(schemaType);
    populateDistributionPackageDTO(deploymentUnitDto, schemaType);
    populateServerLogsDTO(deploymentUnitDto, schemaType);
    populateBusinessFunctions(deploymentUnitDto, schemaType);
    populateDependentResourceList(deploymentUnitDto, schemaType);
    populateDeploymentTargets(deploymentUnitDto, schemaType);
    return deploymentUnitDto;
  }

  private static DeploymentUnitDTO populateDeploymentUnitDTO(final DeploymentUnit schemaType) {
    DeploymentUnitDTO duDto = new DeploymentUnitDTO();
    duDto.setName(schemaType.getName());
    duDto.setType(schemaType.getType());
    duDto.setDeploymentStrategy(schemaType.getDeploymentStrategy());
    duDto.setEnvironmentType(schemaType.getEnvironmentType());
    duDto.setFunctionGroup(schemaType.getFunctionGroup());
    return duDto;
  }

  private static void populateDistributionPackageDTO(final DeploymentUnitDTO deploymentUnitDto,
      final DeploymentUnit schemaType) {
    if (schemaType.getDistributionPackage() != null) {
      DistributionPackageDTO distributionPackageDTO = new DistributionPackageDTO();
      distributionPackageDTO.setName(schemaType.getDistributionPackage().getName());
      distributionPackageDTO.setType(schemaType.getDistributionPackage().getType());
      deploymentUnitDto.setDistributionPackage(distributionPackageDTO);
    }
  }

  private static void populateServerLogsDTO(final DeploymentUnitDTO deploymentUnitDto, final DeploymentUnit schemaType) {
    if (schemaType.getServerLogs() != null) {
      ServerLogsDTO serverLogsDTO = new ServerLogsDTO();
      serverLogsDTO.setAbsoluteLogDirectoryPath(schemaType.getServerLogs().getAbsoluteLogDirectoryPath());
      serverLogsDTO.setFileExtensionFilter(schemaType.getServerLogs().getFileExtensionFilter());
      serverLogsDTO.setFileNameFilter(schemaType.getServerLogs().getFileNameFilter());
      deploymentUnitDto.setServerLogs(serverLogsDTO);
    }
  }

  private static void populateDeploymentTargets(final DeploymentUnitDTO deploymentUnitDto,
      final DeploymentUnit schemaType) {
    for (Host schemaHost : schemaType.getDeploymentTarget().getHost()) {
      HostDTO hostDTO = new HostDTO();
      populateServerClusterDTO(hostDTO, schemaHost);
      populateContainerClusterDTO(hostDTO, schemaHost);
      deploymentUnitDto.getHost().add(hostDTO);
    }
  }

  private static void populateServerClusterDTO(final HostDTO hostDTO, final Host schemaHost) {
    if (schemaHost.getServerCluster() != null) {
      ServerClusterDTO serverClusterDTO = new ServerClusterDTO();
      serverClusterDTO.setIdentifier(schemaHost.getServerCluster().getIdentifier());
      serverClusterDTO.setType(schemaHost.getServerCluster().getType());
      serverClusterDTO.setOperatingSystem(schemaHost.getServerCluster().getOperatingSystem());
      populateServerClusterServer(serverClusterDTO, schemaHost.getServerCluster().getServerClusterServer());
      if (schemaHost.getServerCluster().getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaHost.getServerCluster().getMonitorList().getMonitor());
        serverClusterDTO.setMonitor(monitorDtoList);
      }
      hostDTO.setServerCluster(serverClusterDTO);
    }
  }

  private static void populateServerClusterServer(final ServerClusterDTO serverClusterDTO,
      final List<ServerClusterServer> serverClusterServerList) {
    for (ServerClusterServer schemaServer : serverClusterServerList) {
      ServerClusterServerDTO serverClusterServerDTO = new ServerClusterServerDTO();
      serverClusterServerDTO.setName(schemaServer.getName());
      if (schemaServer.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaServer.getMonitorList().getMonitor());
        serverClusterServerDTO.setMonitor(monitorDtoList);
      }
      serverClusterDTO.getServerClusterServer().add(serverClusterServerDTO);
    }
  }

  private static void populateContainerClusterDTO(final HostDTO hostDTO, final Host schemaHost) {
    if (schemaHost.getContainerCluster() != null) {
      ContainerClusterDTO containerClusterDTO = new ContainerClusterDTO();
      containerClusterDTO.setIdentifier(schemaHost.getContainerCluster().getIdentifier());
      containerClusterDTO.setType(schemaHost.getContainerCluster().getType());
      containerClusterDTO.setDomain(schemaHost.getContainerCluster().getDomain());
      populateContainerClusterServer(containerClusterDTO, schemaHost.getContainerCluster().getContainerClusterServer());
      if (schemaHost.getContainerCluster().getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaHost.getContainerCluster().getMonitorList().getMonitor());
        containerClusterDTO.setMonitor(monitorDtoList);
      }
      hostDTO.setContainerCluster(containerClusterDTO);
    }
  }

  private static void populateContainerClusterServer(final ContainerClusterDTO containerClusterDTO,
      final List<ContainerClusterServer> containerClusterServerList) {
    for (ContainerClusterServer schemaContainer : containerClusterServerList) {
      ContainerClusterServerDTO containerClusterServerDTO = new ContainerClusterServerDTO();
      containerClusterServerDTO.setName(schemaContainer.getName());
      if (schemaContainer.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaContainer.getMonitorList().getMonitor());
        containerClusterServerDTO.setMonitor(monitorDtoList);
      }
      containerClusterDTO.getContainerClusterServer().add(containerClusterServerDTO);
    }
  }

  private static void populateBusinessFunctions(final DeploymentUnitDTO deploymentUnitDto,
      final DeploymentUnit schemaType) {
    for (BusinessFunction businessFunction : schemaType.getAdvertisedBusinessFunctions().getBusinessFunction()) {
      BusinessFunctionDTO businessFunctionDto = new BusinessFunctionDTO();
      populateBusinessFunctionEventType(businessFunctionDto, businessFunction);
      populateBusinessFunctionServiceType(businessFunctionDto, businessFunction);
      populateBusinessFunctionOther(businessFunctionDto, businessFunction);
      deploymentUnitDto.getBusinessFunction().add(businessFunctionDto);
    }

  }

  private static void populateBusinessFunctionServiceType(final BusinessFunctionDTO businessFunctionDto,
      final BusinessFunction businessFunction) {
    if (businessFunction.getService() != null) {
      BusinessFunctionServiceType schemaBusinessFunction = businessFunction.getService();
      BusinessFunctionServiceTypeDTO businessFunctionServiceTypeDTO = new BusinessFunctionServiceTypeDTO();
      businessFunctionServiceTypeDTO.setServiceName(schemaBusinessFunction.getServiceName());
      businessFunctionServiceTypeDTO.setType(schemaBusinessFunction.getType());
      businessFunctionServiceTypeDTO.setDirection(schemaBusinessFunction.getDirection());
      businessFunctionServiceTypeDTO.setVersion(schemaBusinessFunction.getVersion());
      if (schemaBusinessFunction.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaBusinessFunction.getMonitorList().getMonitor());
        businessFunctionServiceTypeDTO.setMonitor(monitorDtoList);
      }
      businessFunctionDto.setService(businessFunctionServiceTypeDTO);
    }
  }

  private static void populateBusinessFunctionEventType(final BusinessFunctionDTO businessFunctionDto,
      final BusinessFunction businessFunction) {
    if (businessFunction.getEvent() != null) {
      BusinessFunctionEventType schemaBusinessFunction = businessFunction.getEvent();
      BusinessFunctionEventTypeDTO businessFunctionEventTypeDTO = new BusinessFunctionEventTypeDTO();
      businessFunctionEventTypeDTO.setEventName(schemaBusinessFunction.getEventName());
      businessFunctionEventTypeDTO.setType(schemaBusinessFunction.getType());
      businessFunctionEventTypeDTO.setDirection(schemaBusinessFunction.getDirection());
      businessFunctionEventTypeDTO.setVersion(schemaBusinessFunction.getVersion());
      if (schemaBusinessFunction.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaBusinessFunction.getMonitorList().getMonitor());
        businessFunctionEventTypeDTO.setMonitor(monitorDtoList);
      }
      businessFunctionDto.setEvent(businessFunctionEventTypeDTO);
    }
  }

  private static void populateBusinessFunctionOther(final BusinessFunctionDTO businessFunctionDto,
      final BusinessFunction businessFunction) {
    if (businessFunction.getBusinessFunctionOther() != null) {
      BusinessFunctionOther schemaBusinessFunction = businessFunction.getBusinessFunctionOther();
      BusinessFunctionOtherDTO businessFunctionOtherDTO = new BusinessFunctionOtherDTO();
      businessFunctionOtherDTO.setName(schemaBusinessFunction.getName());
      businessFunctionOtherDTO.setType(schemaBusinessFunction.getType());
      businessFunctionOtherDTO.setBusinessDescription(schemaBusinessFunction.getBusinessDescription());
      businessFunctionOtherDTO.setArtifactId(schemaBusinessFunction.getArtifactId());
      if (schemaBusinessFunction.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaBusinessFunction.getMonitorList().getMonitor());
        businessFunctionOtherDTO.setMonitor(monitorDtoList);
      }
      businessFunctionDto.setBusinessFunctionOther(businessFunctionOtherDTO);
    }
  }

  private static void populateDependentResourceList(final DeploymentUnitDTO deploymentUnitDto,
      final DeploymentUnit schemaType) {
    for (Resource schemaResource : schemaType.getDependentResourceList().getResource()) {
      ResourceDTO resourceDTO = new ResourceDTO();
      populateResourceMessagingChannels(resourceDTO, schemaResource);
      populateResourceEvent(resourceDTO, schemaResource);
      populateResourceService(resourceDTO, schemaResource);
      populateResourceRepository(resourceDTO, schemaResource);
      deploymentUnitDto.getResource().add(resourceDTO);
    }
  }

  private static void populateResourceService(final ResourceDTO resourceDTO, final Resource schemaResource) {
    if (schemaResource.getService() != null) {
      ResourceServiceType schemaResourceServiceType = schemaResource.getService();
      ResourceServiceTypeDTO resourceServiceTypeDTO = new ResourceServiceTypeDTO();
      resourceServiceTypeDTO.setServiceName(schemaResourceServiceType.getServiceName());
      resourceServiceTypeDTO.setType(schemaResourceServiceType.getType());
      resourceServiceTypeDTO.setVersion(schemaResourceServiceType.getVersion());
      resourceServiceTypeDTO.setDirection(schemaResourceServiceType.getDirection());
      if (schemaResourceServiceType.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaResourceServiceType.getMonitorList().getMonitor());
        resourceServiceTypeDTO.setMonitor(monitorDtoList);
      }
      resourceDTO.setService(resourceServiceTypeDTO);
    }
  }

  private static void populateResourceRepository(final ResourceDTO resourceDTO, final Resource schemaResource) {
    if (schemaResource.getRepository() != null) {
      Repository schemaResourceRepository = schemaResource.getRepository();
      RepositoryDTO resourceRepositoryDTO = new RepositoryDTO();
      resourceRepositoryDTO.setRepositoryName(schemaResourceRepository.getRepositoryName());
      resourceRepositoryDTO.setType(schemaResourceRepository.getType());
      if (schemaResourceRepository.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaResourceRepository.getMonitorList().getMonitor());
        resourceRepositoryDTO.setMonitor(monitorDtoList);
      }
      resourceDTO.setRepository(resourceRepositoryDTO);
    }
  }

  private static void populateResourceEvent(final ResourceDTO resourceDTO, final Resource schemaResource) {
    if (schemaResource.getEvent() != null) {
      ResourceEventType schemaResourceEventType = schemaResource.getEvent();
      ResourceEventTypeDTO resourceEventTypeDTO = new ResourceEventTypeDTO();
      resourceEventTypeDTO.setEventName(schemaResourceEventType.getEventName());
      resourceEventTypeDTO.setType(schemaResourceEventType.getType());
      resourceEventTypeDTO.setDirection(schemaResourceEventType.getDirection());
      resourceEventTypeDTO.setVersion(schemaResourceEventType.getVersion());
      if (schemaResourceEventType.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaResourceEventType.getMonitorList().getMonitor());
        resourceEventTypeDTO.setMonitor(monitorDtoList);
      }
      resourceDTO.setEvent(resourceEventTypeDTO);
    }
  }

  private static void populateResourceMessagingChannels(final ResourceDTO resourceDTO, final Resource schemaResource) {
    if (schemaResource.getMessagingChannel() != null) {
      MessagingChannel schemaResourceMessagingChannel = schemaResource.getMessagingChannel();
      MessagingChannelDTO resourceMessagingChannelDTO = new MessagingChannelDTO();
      resourceMessagingChannelDTO.setName(schemaResourceMessagingChannel.getName());
      resourceMessagingChannelDTO.setType(schemaResourceMessagingChannel.getType());
      resourceMessagingChannelDTO.setDirection(schemaResourceMessagingChannel.getDirection());
      resourceMessagingChannelDTO.setConnectionFactories(schemaResourceMessagingChannel.getConnectionFactories());
      populateMessageChannelInstance(resourceMessagingChannelDTO, schemaResourceMessagingChannel);
      if (schemaResourceMessagingChannel.getMonitorList() != null) {
        List<MonitorDTO> monitorDtoList = new ArrayList<MonitorDTO>();
        populateMonitorDto(monitorDtoList, schemaResourceMessagingChannel.getMonitorList().getMonitor());
        resourceMessagingChannelDTO.setMonitor(monitorDtoList);
      }
      resourceDTO.setMessagingChannel(resourceMessagingChannelDTO);
    }
  }

  private static void populateMessageChannelInstance(final MessagingChannelDTO resourceMessagingChannelDTO,
      final MessagingChannel schemaResourceMessagingChannel) {
    if (schemaResourceMessagingChannel.getInstance() != null) {
      MessageChannelInstanceDTO resourceMessageChannelInstanceDTO = new MessageChannelInstanceDTO();
      resourceMessageChannelInstanceDTO.setInstanceName(schemaResourceMessagingChannel.getInstance().getInstanceName());
      resourceMessageChannelInstanceDTO.setType(schemaResourceMessagingChannel.getInstance().getType());
      resourceMessagingChannelDTO.setInstance(resourceMessageChannelInstanceDTO);
    }
  }

  private static void populateMonitorDto(final List<MonitorDTO> monitorDtoList, final List<Monitor> monitors) {
    for (Monitor monitor : monitors) {
      MonitorDTO monitorDto = new MonitorDTO();
      monitorDto.setMonitorId(monitor.getId());
      monitorDto.setMonitorName(monitor.getName());
      monitorDto.setMonitorType(monitor.getType());
      monitorDto.setMonitorPortNumber(monitor.getPortNumber());
      monitorDtoList.add(monitorDto);
    }
  }
}
